/**
 * 
 */
package UnitTests;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import RefactoringA1.src.Bank;
import RefactoringA1.src.CheckingAccount;

/**
 * @author Thomas
 *
 */
public class CheckingAccountTest {

	/**
	 * A Bank Object for testing.
	 */
	Bank myBank;
	
	/**
	 * A checking account number.
	 */
	int checkAccNum;

	/**
	 * A CheckingAccount for testing.
	 */
	CheckingAccount ca3;
	
	/**
	 * A CheckingAccount for testing.
	 */
	CheckingAccount ca2;
	
	
	
	/**
	 * @throws java.lang.Exception
	 */
	@Before
	public void setUp() throws Exception {
		myBank = new Bank("TestBank");
		checkAccNum = myBank.openSimpleCheckingAccount();
		ca3 = new CheckingAccount(checkAccNum);
		ca2= new CheckingAccount("Bobby", "Maple", "98500", "Anytown", "usa", 5000);
		
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#CheckingAccount(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)}.
	 */
	@Test
	public void testCheckingAccountStringStringStringStringString() {
		final CheckingAccount ca1= new CheckingAccount("Bobby", "Maple", "98500", "Anytown", "USA", 250);
		Assert.assertTrue(ca1 instanceof CheckingAccount);
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#CheckingAccount(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, float)}.
	 */
	@Test
	public void testCheckingAccountStringStringStringStringStringFloat() {
		
		Assert.assertTrue(ca2 instanceof CheckingAccount);
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#CheckingAccount(int)}.
	 */
	@Test
	public void testCheckingAccountInt() {
		Assert.assertTrue(ca3 instanceof CheckingAccount);
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#determineCosts()}.
	 */
	@Test
	public void testDetermineCosts() {
		ca3.setBalance(-1.00);
		double bal1 = ca3.getBalance();
		ca3.determineCosts();
		Assert.assertTrue(bal1 > ca3.getBalance());
		ca3.setBalance(500.00);
		bal1 = ca3.getBalance();
		ca3.determineCosts();
		Assert.assertFalse(bal1 < ca3.getBalance());
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#withdrawal(double)}.
	 */
	@Test
	public void testWithdrawal() {
		Assert.assertFalse(ca3.withdrawal(10.00));
		Assert.assertTrue(ca2.withdrawal(5001.00));
		ca2.setBalance(1000.00);
		Assert.assertFalse(ca2.withdrawal(5000.00));
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#verseMoney(double)}.
	 */
	@Test
	public void testVerseMoney() {
		final double bal2 = ca3.getBalance();
		ca3.verseMoney(1000.00);
		Assert.assertTrue(bal2 + 1000.00 == ca3.getBalance());
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#applyForCreditCard(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String, int)}.
	 */
	@Test
	public void testApplyForCreditCard() {
		ca3.setBalance(-5.00);
		Assert.assertFalse(ca3.applyForCreditCard("Bobbie", "Mapple", "98508", "Atown", "USA", checkAccNum));
		ca3.setBalance(2000.00);
		Assert.assertTrue(ca3.applyForCreditCard("Bobbie", "Mapple", "98508", "Atown", "USA", checkAccNum));
		ca3.setBalance(50000.00);
		Assert.assertTrue(ca3.applyForCreditCard("Bobbie", "Mapple", "98508", "Atown", "USA", checkAccNum));
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#getBalance()}.
	 */
	@Test
	public void testGetBalance() {
		final CheckingAccount c = new CheckingAccount("Bobby", "Maple", "98500", "Anytown", "USA", 250);
		Assert.assertTrue(c.getBalance() == 250);
		c.increaseBalance(1000.00);
		Assert.assertTrue(c.getBalance() == 1250.00);
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#increaseBalance(double)}.
	 */
	@Test
	public void testIncreaseBalance() {
		final double bal3 = ca3.getBalance();
		ca3.increaseBalance(1000.00);
		Assert.assertTrue(bal3 + 1000.00 == ca3.getBalance());
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#decreaseBalance(double)}.
	 */
	@Test
	public void testDecreaseBalance() {
		final double bal3 = ca3.getBalance();
		ca3.decreaseBalance(1000.00);
		Assert.assertTrue(bal3 - 1000.00 == ca3.getBalance());
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#getDebitAmount()}.
	 */
	@Test
	public void testGetDebitAmount() {
		Assert.assertTrue(ca2.getDebitAmount() == 5000);
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#setBalance(double)}.
	 */
	@Test
	public void testSetBalance() {
		ca3.setBalance(100000.00);
		Assert.assertTrue(ca3.getBalance() == 100000.00);
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#getAccountNumber()}.
	 */
	@Test
	public void testGetAccountNumber() {
		Assert.assertEquals(checkAccNum, ca3.getAccountNumber());
	}

	/**
	 * Test method for {@link RefactoringA1.src.CheckingAccount#equals(java.lang.Object)}.
	 */
	@Test
	public void testEqualsObject() {
		final CheckingAccount c3 = new CheckingAccount(ca3.getAccountNumber());
		final CheckingAccount c4 = new CheckingAccount("Bob", "Mae", "98509", "Antown", "zimbabwe", 250);
		Assert.assertFalse(c3.equals(c4));
		Assert.assertEquals(c3, ca3);
	}

	/**
	 * Test method for {@link java.lang.Object#Object()}.
	 */
	@Test
	public void testObject() {
		Assert.assertTrue(ca3 instanceof CheckingAccount);
	}

	/**
	 * Test method for {@link java.lang.Object#getClass()}.
	 */
	@Test
	public void testGetClass() {
		Assert.assertTrue(ca3.getClass().getSimpleName().equals("CheckingAccount"));
	}
	
	/**
	 * Tests the print method of CheckingAccount.
	 */
	@Test
	public void testPrint() {
		
		final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
		System.setOut(new PrintStream(outContent));
		ca2.print();
		String printResults = outContent.toString();
		System.setOut(null);
		
		final ByteArrayOutputStream outContent2 = new ByteArrayOutputStream();
		System.setOut(new PrintStream(outContent2));
		ca2.print();
		String printResults2 = outContent2.toString();
		System.setOut(null);

		Assert.assertEquals(printResults, printResults2);
	}
	
	@After
	public void cleanUpStreams() {
	    System.setOut(null);
	}
}
